import numpy as np
import math
from typing import List
from common.params import SoftParams, CasingParams


# 工具流体阻力的计算

# 1.先计算各个几面对应的界面面积和流速
# 计算截面1的面积   套管处的面积
def get_casing_area(params: SoftParams) -> float:
    # 获取套管信息列表
    casings: List[CasingParams] = params.casings
    # 获取最后一个套管的信息
    last_casing: CasingParams = casings[-1]
    # 计算截面1的面积
    casing_area: float = 0.25 * math.pi * math.pow(last_casing.d, 2)
    return casing_area


# 计算截面2的面积 套管和工具之间的面积
def get_casing_tool_area(params: SoftParams) -> float:
    # 获取套管信息列表
    casings: List[CasingParams] = params.casings
    # 获取最后一个套管的信息
    last_casing: CasingParams = casings[-1]
    # 计算截面2的面积
    casing_area: float = 0.25 * math.pi * (math.pow(last_casing.d, 2)-math.pow(params.d1, 2))
    return casing_area


# 计算截面3的面积 套管和电缆之间的面积
def get_casing_cable_area(params: SoftParams) -> float:
    # 获取套管信息列表
    casings: List[CasingParams] = params.casings
    # 获取最后一个套管的信息
    last_casing: CasingParams = casings[-1]
    # 计算截面3的面积
    casing_area: float = 0.25 * math.pi * (math.pow(last_casing.d, 2)-math.pow(params.d2, 2))
    return casing_area


# 计算截面1的流速
def get_casing_speed(params: SoftParams) -> float:
    A1: float = get_casing_area(params)
    Q1: float = params.Q_min
    if Q1 == 0:
        return 0
    else:
        V1: float = Q1 / A1 / 60
        return V1


# 计算截面2的流速
def get_casing_tool_speed(params: SoftParams) -> float:
    A2: float = get_casing_tool_area(params)
    Q1: float = params.Q_min
    if Q1 == 0:
        return 0
    else:
        V2: float = Q1 / A2 / 60
        return V2


# 计算截面3的流速
def get_casing_cable_speed(params: SoftParams) -> float:
    A3: float = get_casing_cable_area(params)
    Q1: float = params.Q_min
    if Q1 == 0:
        return 0
    else:
        V3: float = Q1 / A3 / 60
        return V3


# 计算仪器与套管的等效直径
def get_casing_tool(params: SoftParams) -> float:
    # 获取套管信息列表
    casings: List[CasingParams] = params.casings
    # 获取最后一个套管的信息
    last_casing: CasingParams = casings[-1]
    # 计算仪器与套管的等效直径
    d_e: float = last_casing.d - params.d1
    return d_e


# 2.计算截面2的雷诺数
def get_reynolds_number(params: SoftParams) -> float:
    p_m: float = params.rou_m
    Q1: float = params.Q_min
    if Q1 == 0:
        return 0
    else:
        V2: float = get_casing_tool_speed(params)
        d_e: float = get_casing_tool(params)
        re: float = p_m * V2 * d_e / params.tao_p
        return re


# 3.计算穆迪摩擦系数
# 首先判断雷诺数的值  如果小于等于2000，就是层流     如果大于2000，就是湍流
# 在计算湍流的时候，如果是光滑壁面就计算光滑壁面的  如果是粗糙壁面就计算粗糙壁面的
def get_moody_friction_coefficient(params: SoftParams) -> float:
    # 计算仪器与套管的等效直径
    d_e: float = get_casing_tool(params)
    # 计算雷诺数
    re: float = get_reynolds_number(params)
    Q1: float = params.Q_min
    if Q1 == 0:
        return 0
    else:
        if re <= 2100:
            # 层流
            f_m: float = 64 / re
            return f_m
        elif re > 2100:
            if params.is_smooth_surface:
                # 光滑壁面
                f_m: float = 0.3164 / math.pow(re, 0.25)
                return f_m
            else:
                # 粗糙壁面
                # 绝对粗糙度
                epsilon: float = params.absolute_roughness
                factor_a: float = 6.9 / re
                factor_b: float = math.pow(epsilon / d_e / 3.7, 1.11)
                factor_c: float = (-1.8) * math.log10(factor_a + factor_b)
                f_m: float = math.pow(1 / factor_c, 2)
                return f_m


#  4.计算沿程摩擦压力损失
def get_pressure_loss(params: SoftParams) -> float:
    Q1: float = params.Q_min
    if Q1 == 0:
        return 0
    else:
        # 计算穆迪摩擦系数
        f_m: float = get_moody_friction_coefficient(params)
        # 计算仪器与套管的等效直径
        de: float = get_casing_tool(params)
        # 计算截面2的流速
        V2: float = get_casing_tool_speed(params)
        # 计算沿程摩擦压力损失
        p_f: float = (f_m * params.rou_m * math.pow(V2, 2) * params.L1) / (2 * de)
        return p_f


# 5.计算偏心系数
def get_offset_coefficient(params: SoftParams) -> float:
    Q1: float = params.Q_min
    if Q1 == 0:
        return 0
    else:
        # 获取偏心度
        E_c: float = params.skewness
        # 计算雷诺数
        re: float = get_reynolds_number(params)
        # 获取套管信息列表
        casings: List[CasingParams] = params.casings
        # 获取最后一个套管的信息
        last_casing: CasingParams = casings[-1]
        factor_a: float = params.d1 / last_casing.d
        if re <= 2100:
            # 层流
            if E_c == 0:
                # 偏心度为0
                psi: float = 1
                return psi
            else:
                # 偏心度不为0
                psi: float = 1 - 0.072 * E_c * math.pow(factor_a, 0.8454) \
                                            - 3/2 * math.pow(E_c, 2) * math.pow(factor_a, 0.1852) \
                                            + 0.96 * math.pow(E_c, 3) * math.pow(factor_a, 0.2527)
                return psi
        elif re > 2000:
            # 湍流
            if E_c == 0:
                # 偏心度为0
                psi: float = 1
                return psi
            else:
                # 偏心度不为0
                psi: float = 1 - 0.048 * E_c * math.pow(factor_a, 0.8454) \
                                            - 2 / 3 * math.pow(E_c, 2) * math.pow(factor_a, 0.1852) \
                                            + 0.285 * math.pow(E_c, 3) * math.pow(factor_a, 0.2527)
                return psi


# 6.计算偏心环空的摩擦压力损失
def get_offset_pressure_loss(params: SoftParams) -> float:
    Q1: float = params.Q_min
    if Q1 == 0:
        return 0
    else:
        # 计算偏心系数
        psi: float = get_offset_coefficient(params)
        # 计算沿程摩擦压力损失
        p_f: float = get_pressure_loss(params)
        p_fecc: float = p_f * psi
        return p_fecc


# 7.计算粘性阻力
def get_frictional_force(params: SoftParams) -> float:
    Q1: float = params.Q_min
    if Q1 == 0:
        return 0
    else:
        # 计算偏心环空的摩擦压力损失
        p_fecc: float = get_offset_pressure_loss(params)
        # 计算套管和工具之间的面积等效直径
        de: float = get_casing_tool(params)
        f_s: float = de * 0.25 * math.pi * params.d1 * p_fecc
        return f_s


# 8.计算压力阻力
def get_pressure_force(params: SoftParams) -> float:
    Q1: float = params.Q_min
    if Q1 == 0:
        return 0
    else:
        # 计算偏心环空的摩擦压力损失
        p_fecc: float = get_offset_pressure_loss(params)
        # 获取工具面积
        A: float = params.A1
        f_p: float = A * p_fecc
        return f_p


# 9.计算长工具和短工具共同所需参数------计算收缩系数
def get_shrinkage_coefficient(params: SoftParams) -> float:
    A1: float = get_casing_area(params)
    A2: float = get_casing_tool_area(params)
    C_c: float = 0.6349 - 0.1697 * (A2 / A1) + 0.5145 * math.pow(A2 / A1, 2)
    return C_c


# 9.计算长工具和短工具共同所需参数------不考虑由于收缩造成的不可逆损失
def get_irreversible_loss(params: SoftParams)-> float:
    # 计算A1面积
    A1: float = get_casing_area(params)
    # 计算A2面积
    A2: float = get_casing_tool_area(params)
    # 计算收缩系数
    C_c: float = get_shrinkage_coefficient(params)
    # 计算收缩腔的速度
    V_vc: float = params.Q_min / (C_c * A2) / 60
    # 计算不可逆损失
    p_c: float = 0.5 * params.rou_m * math.pow(V_vc, 2) * (1 - math.pow(C_c * A2 / A1, 2))
    return p_c


# 9.计算长工具和短工具共同所需参数------截面2到截面3的突然膨胀，存在可逆压力增量
def get_reversible_pressure_increment(params: SoftParams)-> float:
    # 计算A2面积
    A2: float = get_casing_tool_area(params)
    # 计算A3面积
    A3: float = get_casing_cable_area(params)
    # 计算截面2的流速
    V2: float = get_casing_tool_speed(params)
    # 计算可逆压力增量
    p_e: float = 0.5 * params.rou_m * math.pow(V2, 2) * (1 - math.pow(A2 / A3, 2))
    return p_e

# 10.计算工具仪器引起的流体阻力 分为长工具和短工具
def get_fluid_force(params: SoftParams)-> float:
    Q1: float = params.Q_min
    if Q1 == 0:
        return 0
    else:
        # 计算截面2的流速
        V2: float = get_casing_tool_speed(params)
        # 计算V3流速
        V3: float = get_casing_cable_speed(params)
        # 计算A1面积
        A1: float = get_casing_area(params)
        # 计算A2面积
        A2: float = get_casing_tool_area(params)
        # 计算A3面积
        A3: float = get_casing_cable_area(params)
        # 计算收缩系数
        C_c: float = get_shrinkage_coefficient(params)
        # 计算长短工具的不可逆压力损失
        p_c: float = get_irreversible_loss(params)
        # 计算长短工具的可逆压力增量
        p_e: float = get_reversible_pressure_increment(params)
        if params.L1 < 3.0:
            # 计算由于收缩和膨胀引起的不可逆压力损失
            p_l: float = 0.5 * params.rou_m * math.pow(V3, 2) * math.pow((A3 - C_c * A2)/(C_c * A2), 2)
            # 不可逆压力损失
            p_a: float = p_c - p_e + p_l
            return p_a
        elif params.L1 >= 3.0:
            # 计算由于收缩造成的压力损失
            p_l_c: float = math.pow(1 / C_c - 1, 2) * 0.5 * params.rou_m * math.pow(V2, 2)
            # print("plc压力损失为：", p_l_c)
            # 计算膨胀系数
            factor_a: float = 1 - math.pow(A2 / A3, 2)
            K: float = math.pow(factor_a, 2)
            # print("K膨胀系数为：", K)
            p_l_e: float = 0.5 * K * params.rou_m * math.pow(V2, 2)
            # print("ple压力损失为：", p_l_e)
            # 计算工具仪器引起的流体阻力
            p_a: float = p_c - p_e + p_l_c + p_l_e
            return p_a


# 11.计算工具仪器形状引起的流体阻力
def get_shape_force(params: SoftParams)-> float:
    Q1: float = params.Q_min
    if Q1 == 0:
        return 0
    else:
        # 计算不可逆压力损失
        p_a: float = get_fluid_force(params)
        f_a: float = p_a * params.A1
        return f_a


# 11.计算工具仪器引起的总阻力
def get_tool_total_force(params: SoftParams)-> float:
    Q1: float = params.Q_min
    if Q1 == 0:
        return 0
    else:
        # 计算粘性阻力
        f_s: float = get_frictional_force(params)
        # 计算压力阻力
        f_p: float = get_pressure_force(params)
        # 计算工具仪器引起的流体阻力
        f_a: float = get_shape_force(params)
        # 计算工具仪器引起的总阻力
        f_t: float = f_s + f_p + f_a
        return f_t










